package com.xing.book.util;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

//三个基本功能 （1）注册驱动 （2）获取连接 （3）释放资源
public class DbUtils_druid {
    //创建数据源对象
    private static DruidDataSource dataSource;
    //创建线程本地变量
    private static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();


    static {
         try {
             Properties properties = new Properties();
             InputStream is = DbUtils_druid.class.getClassLoader().getResourceAsStream("druid.properties");
             properties.load(is);
             is.close();

             dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);

         } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //(2）获取连接
    public static Connection getConnection(){
        try {
            Connection connection = threadLocal.get();
            if(connection==null){
            connection = dataSource.getConnection();
            threadLocal.set(connection);  //线程绑定连接
            }
            return connection;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }
    //（3）释放资源
    public static void closeAll(ResultSet resultSet, Statement statement,Connection connection){
        try {
            if(resultSet!=null){
                resultSet.close();
            }
            if(statement!=null){
                statement.close();
            }
            if(connection!=null){
                //判断是否开启事务
                if(connection.getAutoCommit()) {
                    connection.close();
                    threadLocal.remove(); //线程解除绑定
                }
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    //执行增删改方法
    //sql:执行的sql语句
    //params：sql语句的参数
    public static int executeUpdate(String sql,Object...params){
        Connection connection= DbUtils_druid.getConnection();
        PreparedStatement pstat=null;

        try {
            pstat = connection.prepareStatement(sql);
            if(params!=null&&params.length>0){
                for (int i = 0; i < params.length; i++) {
                    pstat.setObject(i+1,params[i]);
                }
            }
            return pstat.executeUpdate();

        }catch (Exception e){
            throw new  RuntimeException(e);
        }finally {
            DbUtils_druid.closeAll(null,pstat,connection);
        }

    }

    //封装一个通用的查询方法（内省技术）
    //泛型：泛型类

public static <T> List<T> selectList(String  sql,Class<T> clazz,Object...params){

    Connection connection= DbUtils_druid.getConnection();
    PreparedStatement pstat=null;
    ResultSet rs=null;

    try {
        List<T> list=new ArrayList<>();
      pstat=connection.prepareStatement(sql);
      if(params!=null&&params.length>0){
          for (int i = 0; i < params.length; i++) {
              pstat.setObject(i+1,params[i]);
          }
      }
        rs=pstat.executeQuery();
      
      //获取结果集的标题
        ResultSetMetaData metaData = rs.getMetaData();
        while (rs.next()){
            //使用类对象创建对象
            T t = clazz.newInstance();
            //属性赋值
            for (int i = 0; i < metaData.getColumnCount(); i++) {

                String columnLabel = metaData.getColumnLabel(i+1);

                try {
                    PropertyDescriptor pd = new PropertyDescriptor(columnLabel, clazz);
                    Method writeMethod = pd.getWriteMethod();
                    writeMethod.invoke(t,rs.getObject(columnLabel));
                } catch (Exception e) {
                   continue;
                }
            }
            list.add(t);
        }
        return list;

    }catch (Exception e){
        e.printStackTrace();
        throw new RuntimeException(e);
    }finally {
        DbUtils_druid.closeAll(rs,pstat,connection);
    }

}


    //四个与事务有关的方法
    public static  void begin() throws SQLException {
        Connection connection=getConnection();
        if(connection!=null){
            connection.setAutoCommit(false);
        }
    }
    public static  void commit() throws SQLException {
        Connection connection=getConnection();
        if(connection!=null){
            connection.commit();
        }
    }
    public static  void rollback() throws SQLException {
        Connection connection=getConnection();
        if(connection!=null){
            connection.rollback();
        }
    }
    public static  void close() throws SQLException {
        Connection connection=getConnection();
        if(connection!=null){
            connection.close();
            threadLocal.remove(); //线程解除绑定
        }
    }

}
